package templatepattern;

/**
 * 模板方法的核心思想是：父类定义骨架，子类实现某些细节
 * 为了防止子类重写父类的骨架方法，可以在父类中对骨架方法使用final
 * 对于需要子类实现的抽象方法，一般声明为protected，使得这些方法对外部客户端不可见
 * Java标准库也有很多模板方法的应用：
 * 在集合类中，AbstractList和AbstractQueuedSynchronizer都定义了很多通用操作，子类只需要实现某些必要方法
 */
public abstract class AbstractSetting {

    /**
     * 由于从数据库读取数据较慢，我们可以考虑把读取的设置缓存起来，这样下一次读取同样的key就不必再访问数据库了;
     * 但是怎么实现缓存，暂时没想好，但不妨碍我们先写出使用缓存的代码
     */
    public final String getSetting(String key) {
        String value = lookupCache(key);
        if (value == null) {
            value = readFromDatabase(key);
            System.out.println("[DEBUG] load from db: " + key + " = " + value);
            putIntoCache(key, value);
        } else {
            System.out.println("[DEBUG] load from cache: " + key + " = " + value);
        }
        return value;
    }

    // 具体实现交给子类实现
    protected abstract String lookupCache(String key);

    // 具体实现交给子类实现
    protected abstract void putIntoCache(String key, String value);

    // 模拟从数据库中读取数据
    private String readFromDatabase(String key) {
        return Integer.toHexString(0x7fffffff & key.hashCode());
    }

}
